package com.zp.drug.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.RemoteSerialNumberUtils;
import com.zp.common.core.constant.BaseConstants;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.SnowIdUtils;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.drug.api.vo.DrugInfoVo;
import com.zp.drug.entity.DrugExportDetail;
import com.zp.drug.entity.DrugExportMaster;
import com.zp.drug.entity.DrugStock;
import com.zp.drug.entity.DrugStorageDept;
import com.zp.drug.entity.bo.DrugExportDetailBo;
import com.zp.drug.entity.bo.DrugExportMasterBo;
import com.zp.drug.entity.vo.DrugExportMasterVo;
import com.zp.drug.entity.vo.DrugStockVo;
import com.zp.drug.mapper.DrugExportDetailMapper;
import com.zp.drug.mapper.DrugExportMasterMapper;
import com.zp.drug.mapper.DrugStockMapper;
import com.zp.drug.service.IDrugExportMasterService;
import com.zp.drug.service.IDrugStockAllLogService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 药品出库主Service业务层处理
 *
 * @author zhang peng
 * @ date 2024-05-23
 */
@RequiredArgsConstructor
@Service
public class DrugExportMasterServiceImpl implements IDrugExportMasterService {

    // 药品基本信息
    static Map<String, DrugInfoVo> drugInfoVoMap = CacheUtils.get(CacheNames.DRUG_INFO);
    // 药品库存单位
    static Map<String, DrugStorageDept> drugStorageDeptMap = CacheUtils.get(CacheNames.DRUG_STORAGE_DEPT);
    private final DrugExportMasterMapper baseMapper;
    private final DrugStockMapper drugStockMapper;
    private final DrugExportDetailMapper drugExportDetailMapper;
    @DubboReference
    private RemoteSerialNumberUtils remoteSerialNumberUtils;
    private final IDrugStockAllLogService drugStockAllLogService;

    /**
     * 查询药品出库主
     */
    @Override
    public DrugExportMasterVo queryById(String exportId) {
        return baseMapper.selectVoById(exportId);
    }

    /**
     * 查询药品出库主列表(分页)
     */
    @Override
    public TableDataInfo<DrugExportMasterVo> queryPageList(DrugExportMasterBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DrugExportMaster> lqw = buildQueryWrapper(bo);
        Page<DrugExportMasterVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(item -> {
            item.setStorageName(ObjectUtil.isNotNull(drugStorageDeptMap.get(item.getStorageId())) ? drugStorageDeptMap.get(item.getStorageId()).getStorageName() : "");
            item.setReceiverIdName(StringUtils.isNotBlank(item.getReceiverId()) && ObjectUtil.isNotNull(drugStorageDeptMap.get(item.getReceiverId()))
                    ? drugStorageDeptMap.get(item.getReceiverId()).getStorageName() : "");
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询药品出库主列表(不分页)
     */
    @Override
    public List<DrugExportMasterVo> queryList(DrugExportMasterBo bo) {
        LambdaQueryWrapper<DrugExportMaster> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DrugExportMaster> buildQueryWrapper(DrugExportMasterBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DrugExportMaster> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getDocumentNo()), DrugExportMaster::getDocumentNo, bo.getDocumentNo());
        lqw.eq(StringUtils.isNotBlank(bo.getStorageId()), DrugExportMaster::getStorageId, bo.getStorageId());
        if (bo.getExportDate() != null) {
            lqw.between(DrugExportMaster::getExportDate,
                    DateUtils.dateTime(bo.getExportDate(), "00:00:00"), DateUtils.dateTime(bo.getExportDate(), "23:59:59"));
        }
        lqw.eq(StringUtils.isNotBlank(bo.getReceiverId()), DrugExportMaster::getReceiverId, bo.getReceiverId());
        lqw.eq(StringUtils.isNotBlank(bo.getReceiverUserId()), DrugExportMaster::getReceiverUserId, bo.getReceiverUserId());
        lqw.eq(bo.getAccountReceivable() != null, DrugExportMaster::getAccountReceivable, bo.getAccountReceivable());
        lqw.eq(bo.getAccountPayed() != null, DrugExportMaster::getAccountPayed, bo.getAccountPayed());
        lqw.eq(bo.getAdditionalFee() != null, DrugExportMaster::getAdditionalFee, bo.getAdditionalFee());
        lqw.eq(StringUtils.isNotBlank(bo.getExportClass()), DrugExportMaster::getExportClass, bo.getExportClass());
        lqw.eq(StringUtils.isNotBlank(bo.getAccountType()), DrugExportMaster::getAccountType, bo.getAccountType());
        lqw.eq(StringUtils.isNotBlank(bo.getAccountIndicator()), DrugExportMaster::getAccountIndicator, bo.getAccountIndicator());
        lqw.eq(bo.getAcctDate() != null, DrugExportMaster::getAcctDate, bo.getAcctDate());
        lqw.eq(StringUtils.isNotBlank(bo.getAcctOperator()), DrugExportMaster::getAcctOperator, bo.getAcctOperator());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), DrugExportMaster::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getImportOperator()), DrugExportMaster::getImportOperator, bo.getImportOperator());
        lqw.eq(bo.getImportDate() != null, DrugExportMaster::getImportDate, bo.getImportDate());
        lqw.eq(StringUtils.isNotBlank(bo.getImportMasterId()), DrugExportMaster::getImportMasterId, bo.getImportMasterId());
        lqw.eq(StringUtils.isNotBlank(bo.getIfBatch()), DrugExportMaster::getIfBatch, bo.getIfBatch());
        lqw.eq(StringUtils.isNotBlank(bo.getIsSelect()), DrugExportMaster::getIsSelect, bo.getIsSelect());
        return lqw;
    }

    /**
     * 新增药品出库主
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo(DrugExportMasterBo bo) {
        // 设置出库主记录主键id
        bo.setExportId(SnowIdUtils.uniqueString());
        // 出库单号
        String drugExportNo = remoteSerialNumberUtils.generateDrugExportNo(bo.getOrgId(), "ckd");
        bo.setDocumentNo(drugExportNo);
        bo.setExportDate(DateUtils.getNowDate());
        bo.setIfBatch(UserConstants.YES);

        // 获取出库药品明细
        List<DrugExportDetailBo> drugExportDetailBos = bo.getDetailListSave();
        // 库存表id集合
        List<String> stockIds = drugExportDetailBos.stream().map(DrugExportDetailBo::getStockId).collect(Collectors.toList());
        // 查询出库前台传的药品的库存信息
        List<DrugStockVo> drugStockVos = drugStockMapper.selectVoList(Wrappers.<DrugStock>lambdaQuery()
                .in(DrugStock::getId, stockIds)
        );
        drugExportDetailBos.forEach(drugExportDetailBo -> {
            int minQuantity = StringUtils.equals(drugExportDetailBo.getPackSize(), BaseConstants.IS_SMALL_PACK) ?
                    drugExportDetailBo.getQuantity() : drugExportDetailBo.getQuantity() * drugExportDetailBo.getPackageNum();
            List<DrugStockVo> collect = drugStockVos.stream()
                    .filter(e -> StringUtils.equals(drugExportDetailBo.getStockId(), e.getId())).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(collect) || minQuantity > collect.get(0).getQuantity()) {
                throw new RuntimeException("药品" + drugExportDetailBo.getDrugName() + "库存量不足，请重新填写出库数量");
            }
            DrugStockVo drugStockVo = collect.get(0);
            drugExportDetailBo.setAllInventory(drugStockVo.getQuantity());
            drugExportDetailBo.setMasterId(bo.getExportId());
            drugExportDetailBo.setStockId(drugStockVo.getId());
            drugExportDetailBo.setPurchasePrice(drugStockVo.getTradePrice());
            drugExportDetailBo.setRetailPrice(drugStockVo.getRetailPrice());
            drugExportDetailBo.setRetailPriceMin(drugStockVo.getRetailPriceMin());
            drugExportDetailBo.setTradePriceMin(drugStockVo.getTradePriceMin());
            drugExportDetailBo.setRevokeType(UserConstants.NO);
            drugExportDetailBo.setSurplusInventory(drugStockVo.getQuantity() - minQuantity);
            drugExportDetailBo.setDelFlag("0");

        });
        DrugExportMaster drugExportMaster = BeanUtil.toBean(bo, DrugExportMaster.class);
        drugExportMaster.initEntity();
        // 保存主表
        baseMapper.insert(drugExportMaster);
        // 保存明细
        return drugExportDetailMapper.insertBatch(BeanUtil.copyToList(drugExportDetailBos, DrugExportDetail.class));
    }


    /**
     * 修改药品出库主
     */
    @Override
    public Boolean updateByBo(DrugExportMasterBo bo) {
        DrugExportMaster update = BeanUtil.toBean(bo, DrugExportMaster.class);
        update.updateInfo();
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DrugExportMaster entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除药品出库主
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
